<?php

namespace longhu\library;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use longhu\base\BaseJWT;
use longhu\exceptions\LoginFailedException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Env;

class VerufyJwt extends BaseJWT
{
    protected $debug = false;

    const TOKEN = "sdfafsdfsdfsdfsdfwefsfs5sfsdfasfsafafasfasdafsfasfsafasfasf";



    public function createToken(int $id,string $type = 'sys',array $params = []):array
    {

        $exp = $params['exp']??config('admin.token_valid_exp',7);
        $exp = strtotime("+ {$exp}day");
        $time = time();
        $host = app('request')->host();
        $params += [
            'iss' => $host,
            'aud' => $host,
            'iat' => $time,
            'nbf' => $time,
            'exp' => $exp,
        ];
        if($this->debug) {
            $params['token'] = self::TOKEN;
            $params['out'] = $exp - time();
            return $params;
        }
        $params['jti'] = [$id, $type];
        $token = JWT::encode($params, config('admin.app_key', 'default'),'HS256');
        $params['token'] = $token;
        $params['out'] = $exp - time();
        $this->cacheToken($type,$token, $params['out']);
        return $params;
    }

    /**
     * 缓存token
     * @param string $type
     * @param string $token
     * @param $exp
     * @param string $tag
     * @return mixed|object|\think\App
     */
    public function cacheToken(string $type,string $token,$exp)
    {
       return cache($type.'_'.$token,time() + $exp,$exp,$type.':');
    }

    /**
     * 验证token
     * @param string $type
     * @param string $token
     * @return array
     */
    public function checkToken(string $type,string $token) : array
    {
        if(empty($token)){
            throw new LoginFailedException('token is not empty');
        }
        if($this->debug){
            return  [];
        }
        $has = Cache::has($type.'_' . $token);
        if(!$has){
            throw new LoginFailedException('token is exp');
        }
        $lastTime = Cache::get($type.'_' . $token,0);
        if (($lastTime + (intval(Config::get('admin.token_valid_exp', 7))) * 60) < time())
            throw new LoginFailedException('token 已过期');
        try {
            JWT::$leeway = 60;
            $data = JWT::decode($token,new Key(Env::get('admin.app_key', 'default'),'HS256')); //HS256方式，这里要和签发的时候对应
            return  (array)$data;
        }catch (\Firebase\JWT\SignatureInvalidException $e){
            throw new LoginFailedException('签名不正确');
        }catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
            throw new LoginFailedException('token过期');
        }catch(\Firebase\JWT\ExpiredException $e) { // token过期
            throw new LoginFailedException('token过期');
        }catch(\Exception $e) { //其他错误
            throw new LoginFailedException('token不可使用');
        }
        return  [];
    }

    public function updateToken(string $type ,string $token)
    {
       return Cache::tag($type.':')->set($type.'_' . $token, time(), intval(Config::get('admin.token_valid_exp', 7)));
    }

    public function clearToken(string $type,string $token)
    {
        Cache::delete($type.'_' . $token);
    }

//    public function ()
//    {
//
//    }
}